#include "../../common/message.pb.h"
#include "../../server/Router.hpp"
#include <gtest/gtest.h>
#include <iostream>
#include <string>

class RouteTest : public testing::Environment
{
public:
    virtual void SetUp() override
    {}

    virtual void TearDown() override
    {}
};

TEST(route_test, __glibcxx_requires_valid_range)
{
    ASSERT_EQ(micromq::Router::isBindingKeyValid("#.ccc.bbb.*.bbb"), true);
    ASSERT_EQ(micromq::Router::isBindingKeyValid("#.*.ccc.bbb.*.bbb"), false);
    ASSERT_EQ(micromq::Router::isRoutingKeyValid("aaa.ddd.ccc.bbb.eee.bbb"), true);
}

TEST(route_test, direct)
{
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::DIRECT, "aaa.ddd.ccc.bbb.eee.bbb", "aaa.ddd.ccc.bbb.eee.bbb"), true);
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::DIRECT, "aaa.ddd.ccc.bbb.eee.bbb", "aaa.ddd.ccc"), false);
}

TEST(route_test, fanout)
{
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::FANOUT, "aaa.ddd.ccc.bbb.eee.bbb", "aaa.ddd.ccc.bbb.eee.bbb"), true);
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::FANOUT, "aaa.ddd.ccc.bbb.eee.bbb", "aaa.ddd.ccc"), true);
}

TEST(route_test, topic)
{ 
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::TOPIC, "#.ccc.bbb.*.bbb", "aaa.ddd.ccc.bbb.eee.bbb"), true);
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::TOPIC, "aaa.#.bbb.*.ddd", "aaa.ddd.aaa.bbb.eee.ddd"), true);
    std::vector<std::string> bkeys = { 
        "aaa", 
        "aaa.bbb", 
        "aaa.bbb", 
        "aaa.bbb", 
        "aaa.bbb.ccc", 
        "aaa.*", 
        "aaa.*.bbb", 
        "*.aaa.bbb", 
        "#", 
        "aaa.#", 
        "aaa.#", 
        "aaa.#.ccc", 
        "aaa.#.ccc", 
        "aaa.#.ccc", 
        "#.ccc", 
        "#.ccc", 
        "aaa.#.ccc.ccc", 
        "aaa.#.bbb.*.bbb" 
    }; 
    std::vector<std::string> rkeys = { 
        "aaa", 
        "aaa.bbb", 
        "aaa.bbb.ccc", 
        "aaa.ccc", 
        "aaa.bbb.ccc", 
        "aaa.bbb", 
        "aaa.bbb.ccc", 
        "aaa.bbb", 
        "aaa.bbb.ccc", 
        "aaa.bbb", 
        "aaa.bbb.ccc", 
        "aaa.ccc", 
        "aaa.bbb.ccc", 
        "aaa.aaa.bbb.ccc", 
        "ccc", 
        "aaa.bbb.ccc", 
        "aaa.bbb.ccc.ccc.ccc", 
        "aaa.ddd.ccc.bbb.eee.bbb" 
    }; 
    std::vector<bool> result = { 
        true, 
        true, 
        false, 
        false, 
        true, 
        true, 
        false, 
        false, 
        true, 
        true, 
        true, 
        true, 
        true, 
        true, 
        true, 
        true, 
        true, 
        true 
    };
    for (int i = 0; i < bkeys.size(); i++) { 
        ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::TOPIC, bkeys[i], rkeys[i]), result[i]);
    }
}

TEST(route_test, topicTest)
{
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::TOPIC, "aaa.bbb.#", "aaa.xxx.yyy"), false);
    ASSERT_EQ(micromq::Router::route(micromq::ExchangeType::TOPIC, "news.music.#", "news.code.debug"), false);
}

int main(int argc, char* argv[])
{
    testing::InitGoogleTest(&argc, argv);
    testing::AddGlobalTestEnvironment(new RouteTest);
    RUN_ALL_TESTS();

    return 0;
}